package eu.catengine.activity;

import java.util.Random;

import android.view.KeyEvent;
import eu.catengine.common.manager.ScreenManager;
import eu.catengine.graphic.Font;
import eu.catengine.primitive.Point;
import eu.catengine.primitive.Vector;
import eu.catengine.renderable.shape.Rectangle;
import eu.catengine.renderable.text.Text;
import eu.catengine.scene.Camera;
import eu.catengine.scene.LayerTree;
import eu.catengine.scene.Scene;
import eu.catengine.scene.TouchPointer;

public class Pong extends Scene
{
    Random random = new Random();
    Font font = getFontManager().get("Verdana", 35);
    ScreenManager screenManager = getScreenManager();

    Camera camera = getCamera();
    LayerTree root = getSceneTree();
    LayerTree hud = getHudTree();

    Rectangle player1, player2, ball;
    Rectangle[] borders;
    Text player1Text, player2Text;
    Vector ballVector;

    int player1Score = 0, player2Score = 0;

    float playerMaxSpeed = 10.0f;
    float screenWidth = screenManager.getScreenWidth();
    float screenHeight = screenManager.getScreenHeight();

    boolean player1Down, player1Up, player2Down, player2Up;

    public Pong(String sceneName)
    {
	super(sceneName);

	player1 = new Rectangle(40, screenHeight / 2, 20, 150);
	player2 = new Rectangle(screenWidth - 60, screenHeight / 2, 20, 150);
	ball = new Rectangle(screenWidth / 2 - 10, screenHeight / 2 + 10, 20, 20);

	borders = new Rectangle[5];
	borders[0] = new Rectangle(0, screenHeight, 10, screenHeight);
	borders[1] = new Rectangle(screenWidth - 10, screenHeight, 10, screenHeight);
	borders[2] = new Rectangle(0, 10, screenWidth, 10);
	borders[3] = new Rectangle(0, screenHeight - 100, screenWidth, 10);
	borders[4] = new Rectangle(0, screenHeight, screenWidth, 10);

	player1Text = new Text("0", 20, screenHeight - 32, font);
	player2Text = new Text("0", screenWidth - 20 - font.getTextWidth("0"), screenHeight - 32, font);

	ballVector = new Vector((float) (5 * Math.signum(random.nextFloat() - 0.5)), (float) (5 * Math.signum(random.nextFloat() - 0.5)));

	root.addObject(player1);
	root.addObject(player2);
	root.addObject(ball);

	for (int i = 0; i < 5; i++)
	{
	    root.addObject(borders[i]);
	}

	hud.addObject(player1Text);
	hud.addObject(player2Text);
	hud.addObject(new Text("SCORE", (screenWidth - font.getTextWidth("SCORE")) / 2, screenHeight - 32, font));

	camera.moveTo(0, screenHeight);
    }

    private void init()
    {
	ball.moveTo(screenWidth / 2 - 10, screenHeight / 2 + 10);
	ballVector = new Vector((float) (5 * Math.signum(random.nextFloat() - 0.5)), (float) (5 * Math.signum(random.nextFloat() - 0.5)));
    }

    private void updateInputs(TouchPointer pointer)
    {
	Point touchPoint = pointer.getSceneTouchPoint();

	if (touchPoint.x < screenWidth / 2)
	{
	    if (touchPoint.y < screenHeight / 2)
	    {
		player1Down = true;
		player1Up = false;
	    }
	    else
	    {
		player1Up = true;
		player1Down = false;
	    }
	}
	else
	{
	    if (touchPoint.y < screenHeight / 2)
	    {
		player2Down = true;
		player2Up = false;
	    }
	    else
	    {
		player2Up = true;
		player2Down = false;
	    }
	}
    }

    @Override
    public void onPointerDown(TouchPointer pointer)
    {
	updateInputs(pointer);
    }

    @Override
    public void onPointerMove(TouchPointer pointer, TouchPointer historicalPointer)
    {
	updateInputs(pointer);
    }

    @Override
    public void onPointerUp(TouchPointer pointer)
    {
	Point touchPoint = pointer.getSceneTouchPoint();

	if (touchPoint.x < screenWidth / 2)
	{
	    player1Down = player1Up = false;
	}
	else
	{
	    player2Down = player2Up = false;
	}
    }

    @Override
    public void onChangeToInactiveScene()
    {
    }

    @Override
    public void onChangeToActiveScene()
    {
    }

    @Override
    public Boolean onButtonDown(int keyCode, KeyEvent event)
    {
	return false;
    }

    @Override
    public void updateScene(float deltaTime, long sceneTime)
    {
	if (player1Up && (player1.getAnchorPoint().y + playerMaxSpeed) < screenHeight - 110)
	{
	    player1.moveBy(0, playerMaxSpeed);
	}
	else if (player1Down && (player1.getAnchorPoint().y - player1.getHeight() - playerMaxSpeed) > 10)
	{
	    player1.moveBy(0, -playerMaxSpeed);
	}

	if (player2Up && (player2.getAnchorPoint().y + playerMaxSpeed) < screenHeight - 110)
	{
	    player2.moveBy(0, playerMaxSpeed);
	}
	else if (player2Down && (player2.getAnchorPoint().y - player2.getHeight() - playerMaxSpeed) > 10)
	{
	    player2.moveBy(0, -playerMaxSpeed);
	}

	// Walls (top and bottom)
	if (ball.getAnchorPoint().y - ball.getHeight() + ballVector.y < 10)
	{
	    ballVector.y *= -1;
	}
	else if (ball.getAnchorPoint().y + ballVector.y > screenHeight - 110)
	{
	    ballVector.y *= -1;
	}

	// Players
	if (player1.isAtPoint(ball.getAnchorPoint()))
	{
	    ballVector.x *= -1;
	}
	else if (player2.isAtPoint(new Point(ball.getAnchorPoint()).add(20, 0)))
	{
	    ballVector.x *= -1;
	}

	// Points
	if (ball.getAnchorPoint().x < 10)
	{
	    player2Score++;
	    player2Text.setText(player2Score + "");
	    player2Text.moveTo(screenWidth - 20 - font.getTextWidth(player2Score + ""), screenHeight - 32);

	    init();
	}
	else if (ball.getAnchorPoint().x + ball.getWidth() > screenWidth - 10)
	{
	    player1Score++;
	    player1Text.setText(player1Score + "");

	    init();
	}

	ball.moveBy(ballVector);

	// Speed up
	setSceneSpeed(1.0f + (sceneTime / 100000.0f));
    }
}
